package com.rtsapp.server.network.protocol.command;

import com.rtsapp.server.logger.LoggerFactory;
import com.rtsapp.server.module.Application;
import com.rtsapp.server.network.protocol.ProtocolInHandler;
import com.rtsapp.server.network.server.NettyServerChannelInitializer;
import com.rtsapp.server.network.session.netty.NettySessionManager;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import com.rtsapp.server.logger.Logger;

import java.util.concurrent.TimeUnit;


public class CommandChannelInitializer extends NettyServerChannelInitializer {

	private static Logger LOGGER = LoggerFactory.getLogger(CommandChannelInitializer.class);


	private boolean useFrameDecoder = true;
	private int maxFrameLength = 1024;
    private int lengthFieldOffser = 0 ;
    private int lengthFieldLength = 4;
	
    // must be @Sharable handler
	private ChannelInboundHandler inHandler;
	// must be @Sharable handler
	private ChannelOutboundHandler outHandler;

	private boolean useTimeout = false;
	private int timeout = 30;

	public boolean isUseFrameDecoder() {
		
		return useFrameDecoder;
	}

	public void setUseTimeout(boolean useTimeout) {
		this.useTimeout = useTimeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public void setUseFrameDecoder(boolean useFrameDecoder) {
		this.useFrameDecoder = useFrameDecoder;
	}


	public void setInHandler(ChannelInboundHandler inHandler) {
		this.inHandler = inHandler;
	}


	public void setOutHandler(ChannelOutboundHandler outHandler) {
		this.outHandler = outHandler;
	}

	

	public ChannelInboundHandler getInHandler() {
		return inHandler;
	}

	public ChannelOutboundHandler getOutHandler() {
		return outHandler;
	}

	public void setMaxFrameLength(int maxFrameLength) {
		this.maxFrameLength = maxFrameLength;
	}

	public void setLengthFieldOffser(int lengthFieldOffser) {
		this.lengthFieldOffser = lengthFieldOffser;
	}

	public void setLengthFieldLength(int lengthFieldLength) {
		this.lengthFieldLength = lengthFieldLength;
	}

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		
		if( this.useFrameDecoder ){
			ch.pipeline().addLast( new LengthFieldBasedFrameDecoder( this.maxFrameLength, this.lengthFieldOffser, this.lengthFieldLength ) );
		}
		
		ch.pipeline().addLast( inHandler );
		ch.pipeline().addLast( outHandler );


		if( useTimeout ) {
			ch.pipeline().addLast(new IdleStateHandler( timeout, 0, 0, TimeUnit.MINUTES));// 客户端30分钟无操作则掉线
			ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
				@Override
				public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
					if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
						IdleStateEvent event = (IdleStateEvent) evt;
						switch (event.state()) {
							case READER_IDLE:
								//关闭session
								if( ctx.channel() != null ) {
									LOGGER.info("channel 超时关闭, channel={}" + ctx.channel() );
								}
								ctx.close();
								break;

							case WRITER_IDLE:
								break;

							case ALL_IDLE:
								break;

							default:
								break;
						}
					}
				}
			});
		}
	}

	
	public boolean initialize( Application application, NettySessionManager sessionManager ){
		
		if( inHandler instanceof ProtocolInHandler){
			
			ProtocolInHandler protocolInHandler = ( ProtocolInHandler) inHandler;
  			
			return protocolInHandler.initialize( application, sessionManager );
			
  		}

		return true;
	}
	
	
	
}
